---
title: Loyalty Tokens
description: Use the Sui Closed-Loop Token standard to create tokens that are only valid within specific workflows and services. One example of Closed-Loop Tokens is a loyalty token.
keywords: [ closed-loop tokens, closed-loop, closed loop, loyalty tokens, token example, create a token, how to create token, SUI token standards ]
---

Using the Sui [Closed-Loop Token](../../../standards/closed-loop-token.mdx) standard, you can create tokens that are valid only for a specific service, like an airline that wants to grant tokens to frequent flyers to purchase tickets or upgrades. 

The following example demonstrates the creation of a loyalty token that bearers can use to make purchases in a digital gift shop.

## Example

The loyalty token example illustrates a loyalty token that is created with the Closed Loop Token standard. If you were to implement this example, the Admin sends `LOYALTY` tokens to the users of your service as a reward for their loyalty. The example creates a `GiftShop` where holders can spend `LOYALTY` tokens to buy `Gift`s.

The `loyalty.move` source file contains the `examples::loyalty` module code that creates the loyalty token. The module includes the One-Time Witness (OTW) that creates the coin (with the same name as the module, `LOYALTY`), possesses only the `drop` ability, and has no fields. These are the characteristics of a OTW, which ensures the `LOYALTY` type has a single instance.

<ImportContent source="examples/move/token/sources/loyalty.move" mode="code" struct="LOYALTY" />

The `init` function of the module uses the `LOYALTY` OTW to create the token. All `init` functions run only during the package publish event. The initializer function makes use of the OTW `LOYALTY` type defined previously in its call to `create_currency`. The function also defines a policy, sending both the policy capability and treasury capability to the address associated with the publish event. The holder of these transferrable capabilities can mint new `LOYALTY` tokens and modify their policies.

<ImportContent source="examples/move/token/sources/loyalty.move" mode="code" fun="init" noComments />

The `LOYALTY` minting function is called `reward_user`. As mentioned previously, the holder of the `TreasuryCap` can call this function to mint new loyalty tokens and send them to the desired address. The function uses the `token::mint` function to create the token and `token::transfer` to send it to the intended recipient. 

<ImportContent source="examples/move/token/sources/loyalty.move" mode="code" fun="reward_user" noComments />

Finally, the example includes a `buy_a_gift` function to handle the redemption of `LOYALTY` tokens for `Gift` types. The function ensures the gift price matches the number of loyalty tokens spent, then uses the `token::spend` function to handle the treasury bookkeeping. 

<ImportContent source="examples/move/token/sources/loyalty.move" mode="code" fun="buy_a_gift" noComments />

### Complete code 

Toggle display of the complete source for this example, including comments, or use the link in the [Related links](#related-links) section to view the project source on GitHub.

<details>

<summary>

`loyalty.move`

</summary>

<ImportContent source="examples/move/token/sources/loyalty.move" mode="code" />

</details>

## Related links

<RelatedLink to="/standards/closed-loop-token.mdx" />
<RelatedLink href="https://github.com/MystenLabs/sui/blob/main/examples/move/token/sources/loyalty.move" label="Source code" desc="The source code in GitHub for this example." />
<RelatedLink to="/guides/developer/coin/in-game-token.mdx" />
<RelatedLink to="/guides/developer/coin/regulated.mdx" />